package com.atguigu2.dao;

import com.utils.JDBCUtilsJiuBan;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 封装了针对于数据表的通用操作
 * BaseDao
 *  DAO: date(base) access object
 * @auther user
 * @date 2021/12/9 - 6:21
 */
public abstract class BaseDao {

    //通用更新操作 -----Version 2.0 -----考虑事务
    public int update(Connection connection, String sql, Object ...args) {
        PreparedStatement preparedStatement = null;
        try {
            //1 获取连接
            //2 预编译sql,返回preparedStatment实例
            preparedStatement = connection.prepareStatement(sql);
            //3 填充占位符
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i+1,args[i]);
            }
            //4 执行
            return preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            JDBCUtilsJiuBan.closeResource(null,preparedStatement);
        }
        return 0;
    }

    //针对于不同表的通用查询操作，返货一条记录----Version 2.0 考虑事务
    public <T> T getInstance(Connection connection,Class<T> clazz,String sql,Object ...args) {
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //1 获取连接
            //2 预编译sql,返回preparedStatment实例
            preparedStatement = connection.prepareStatement(sql);
            //3 填充占位符
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i+1,args[i]);
            }
            //4 执行，返回ResultSet结果集
            resultSet = preparedStatement.executeQuery();
            //5 处理结果集
            //获取元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
            //获取总列数
            int columnCount = metaData.getColumnCount();
            if (resultSet.next()){
                T t = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    //获取列别名
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    //获取列值
                    Object columnValue = resultSet.getObject(i + 1);
                    //通过反射，将clumnValue存储到t对象的columLabel属性中
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t,columnValue);
                }
                return t;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtilsJiuBan.closeResource(null,preparedStatement,resultSet);
        }
        return null;
    }
    //针对于不同表的通用查询操作，返回list-------Version 2.0 考虑事务
    public <T> List<T> getForList(Connection connection,Class<T> clazz, String sql, Object ...args){
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //1 获取连接
            //2 预编译sql,返回perparedStatment实例
            preparedStatement = connection.prepareStatement(sql);
            //3 填充占位符
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i+1,args[i]);
            }
            //4 执行，返回ResultSet结果集
            resultSet = preparedStatement.executeQuery();
            //5 处理结果集
            //5.1 获取元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
            //5.2 获取总列数
            int columnCount = metaData.getColumnCount();
            //5.3 创建结果集
            ArrayList<T> arrayList = new ArrayList<T>();
            while (resultSet.next()){
                T t = clazz.newInstance();
                for (int i = 0; i < columnCount; i++) {
                    //5.4 获取字段别名
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    //5.5 获取字段值
                    Object columnValue = resultSet.getObject(i + 1);
                    //5.6 通过反射，将columnValue存储到t对象的columnLavel属性中
                    Field field = clazz.getDeclaredField(columnLabel);
                    field.setAccessible(true);
                    field.set(t,columnValue);
                }
                arrayList.add(t);
            }
            return arrayList;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            JDBCUtilsJiuBan.closeResource(null,preparedStatement,resultSet);
        }
        return null;
    }
    //特殊情况 组函数 select count(*) from table
    public <E>E getValue(Connection connection, String sql, Object ...args) {
        PreparedStatement preparedStatement = null;
        try {
            //1 获取链接
            //2 预编译sql,返回preparedStatment实例
            preparedStatement = connection.prepareStatement(sql);
            //3 填充占位符
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i+1,args[i]);
            }
            //4 执行,返回ResultSet结果集
            ResultSet resultSet = preparedStatement.executeQuery();
            //5 处理结果集
            if (resultSet.next()){
               return(E) resultSet.getObject(1);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //关闭资源
            JDBCUtilsJiuBan.closeResource(null,preparedStatement);
        }
        return null;
    }
}
